package com.lnj.community.service.Impl;

import com.lnj.community.dao.entity.User;
import com.lnj.community.service.FollowService;
import com.lnj.community.service.UserService;
import com.lnj.community.utiles.RedisKeyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.core.RedisOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SessionCallback;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class FollowServiceImpl implements FollowService {
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private UserService userService;

    @Override
    public void follow(int userId, int entityType, int entityId) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                //获取关注的key
                String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
                //获取粉丝的key
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
                //开启事务
                operations.multi();

                operations.opsForZSet().add(followeeKey, entityId, System.currentTimeMillis());
                operations.opsForZSet().add(followerKey, userId, System.currentTimeMillis());

                return operations.exec();
            }
        });
    }

    @Override
    public void unfollow(int userId, int entityType, int entityId) {
        redisTemplate.execute(new SessionCallback() {
            @Override
            public Object execute(RedisOperations operations) throws DataAccessException {
                //获取关注的key
                String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
                //获取粉丝的key
                String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
                //开启事务
                operations.multi();

                operations.opsForZSet().remove(followeeKey, entityId);
                operations.opsForZSet().remove(followerKey, userId);

                return operations.exec();
            }
        });
    }

    @Override
    public long findFolloweeCount(int userId, int entityType) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
        return redisTemplate.opsForZSet().zCard(followeeKey);
    }

    @Override
    public long findFollowerCount(int entityType, int entityId) {
        String followerKey = RedisKeyUtil.getFollowerKey(entityType, entityId);
        return redisTemplate.opsForZSet().zCard(followerKey);
    }

    @Override
    public boolean hasFollowed(int userId, int entityType, int entityId) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
        return redisTemplate.opsForZSet().score(followeeKey, entityId) != null;
    }

    @Override
    public List<Map<String,Object>> findFollowees(int userId, int entityType, int offset, int limit) {
        String followeeKey = RedisKeyUtil.getFolloweeKey(userId, entityType);
        Set<Integer> set = redisTemplate.opsForZSet().reverseRange(followeeKey, offset, offset + limit - 1);
        if(set==null){
            return null;
        }
        List<Map<String,Object>> list=new ArrayList<>();
        for (Integer id : set) {
            User user = userService.findUserById(id);
            Map<String,Object> userMap=new HashMap<>();
            userMap.put("user",user);
            Double score = redisTemplate.opsForZSet().score(followeeKey, id);
            userMap.put("followTime",new Date(score.longValue()));
            list.add(userMap);
        }
        return list;
    }

    @Override
    public List<Map<String,Object>> findFollowers(int userId, int entityType, int offset, int limit) {
        String followerKey = RedisKeyUtil.getFollowerKey(entityType, userId);
        Set<Integer> set = redisTemplate.opsForZSet().reverseRange(followerKey, offset, offset + limit - 1);
        if(set==null){
            return null;
        }
        List<Map<String,Object>> list=new ArrayList<>();
        for (Integer id : set) {
            User user = userService.findUserById(id);
            Map<String,Object> userMap=new HashMap<>();
            userMap.put("user",user);
            Double score = redisTemplate.opsForZSet().score(followerKey, id);
            userMap.put("followTime",new Date(score.longValue()));
            list.add(userMap);
        }
        return list;
    }
}
